package com.smartleanx.module.hrm.dal.mysql.payroll;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.smartleanx.framework.common.pojo.PageResult;
import com.smartleanx.framework.mybatis.core.mapper.BaseMapperX;
import com.smartleanx.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.smartleanx.module.bpm.enums.task.BpmProcessInstanceStatusEnum;
import com.smartleanx.module.hrm.controller.admin.payroll.vo.PayrollDetailPageReqVO;
import com.smartleanx.module.hrm.dal.dataobject.payroll.PayrollDetailDO;
import com.smartleanx.module.hrm.eums.payroll.PayrollSendStatusEnum;
import com.smartleanx.module.system.enums.customfield.CustomFieldLabelEnum;
import org.apache.ibatis.annotations.Mapper;

import java.util.Collection;
import java.util.List;
import java.util.Objects;

/**
 * 薪资详情 Mapper
 *
 * @author zhangchp
 */
@Mapper
public interface PayrollDetailMapper extends BaseMapperX<PayrollDetailDO> {


    default PayrollDetailDO selectByPayrollIdAndEmployeeId(Long payrollId, Long employeeId){
        return selectOne(new LambdaQueryWrapperX<PayrollDetailDO>()
                .eq(PayrollDetailDO::getPayrollId, payrollId)
                .eq(PayrollDetailDO::getEmployeeId, employeeId));
    }

    default Boolean updateColumnBatchByPayrollIdAndEmployeeId(Collection<PayrollDetailDO> details){
        return updateBatch(details, detail -> Wrappers.lambdaUpdate(PayrollDetailDO.class)
                .set(PayrollDetailDO::getUpdated, true)
                .set(PayrollDetailDO::getApproveResult, detail.getApproveResult())
                .eq(PayrollDetailDO::getPayrollId, detail.getPayrollId())
                .eq(PayrollDetailDO::getEmployeeId, detail.getEmployeeId()));
    }

    default Long selectCountByPayrollIdAndEmployeeId(Long payrollId, Collection<Long> employeeIds){
        return selectCount(new LambdaQueryWrapperX<PayrollDetailDO>()
                .eq(PayrollDetailDO::getPayrollId, payrollId)
                .in(PayrollDetailDO::getEmployeeId, employeeIds));
    }

    default Long selectCountByIdAndPayrollId(Collection<Long> ids, Long payrollId){
        return selectCount(new LambdaQueryWrapperX<PayrollDetailDO>()
                .eq(PayrollDetailDO::getPayrollId, payrollId)
                .inIfPresent(PayrollDetailDO::getId, ids));
    }

    default Long selectCountByPayrollIdAndEmployeeIdAndSendStatus(Long payrollId, Collection<Long> employeeIds, Integer sendStatus){
        return selectCount(new LambdaQueryWrapperX<PayrollDetailDO>()
                .eq(PayrollDetailDO::getPayrollId, payrollId)
                .in(PayrollDetailDO::getEmployeeId, employeeIds)
                .eq(PayrollDetailDO::getSendStatus, sendStatus));
    }

    default Long selectCountByIdAndPayrollIdAndSendStatus(Collection<Long> ids, Long payrollId, Integer sendStatus){
        return selectCount(new LambdaQueryWrapperX<PayrollDetailDO>()
                .eq(PayrollDetailDO::getPayrollId, payrollId)
                .inIfPresent(PayrollDetailDO::getId, ids)
                .eq(PayrollDetailDO::getSendStatus, sendStatus));
    }

    default int updateApproveResult(Integer approveResult, Collection<Long> ids){
        return update(Wrappers.lambdaUpdate(PayrollDetailDO.class)
                .set(PayrollDetailDO::getApproveResult, approveResult)
                .in(PayrollDetailDO::getId, ids));
    }

    default int updateApproveResultAndUpdated(Integer approveResult, Boolean updated, Collection<Long> ids){
        return update(Wrappers.lambdaUpdate(PayrollDetailDO.class)
                .set(PayrollDetailDO::getApproveResult, approveResult)
                .set(PayrollDetailDO::getUpdated, updated)
                .in(PayrollDetailDO::getId, ids));
    }

    default int updateSendStatusAndReadStatusAndConfirmStatusAndFeedbackByPayrollIdAndId(Integer sendStatus, Boolean readStatus, Boolean confirmStatus,
                                                                                         String feedback, Long payrollId, Collection<Long> ids){
        return update(Wrappers.lambdaUpdate(PayrollDetailDO.class)
                .set(PayrollDetailDO::getSendStatus, sendStatus)
                .set(PayrollDetailDO::getReadStatus, readStatus)
                .set(PayrollDetailDO::getConfirmStatus, confirmStatus)
                .set(PayrollDetailDO::getFeedback, feedback)
                .eq(PayrollDetailDO::getPayrollId, payrollId)
                .in(CollUtil.isNotEmpty(ids), PayrollDetailDO::getId, ids));
    }

    default int updateSendStatus(Integer sendStatus, Collection<Long> ids){
        return update(Wrappers.lambdaUpdate(PayrollDetailDO.class)
                .set(PayrollDetailDO::getSendStatus, sendStatus)
                .in(PayrollDetailDO::getId, ids));
    }

    default List<PayrollDetailDO> selectListByPayrollId(Long payrollId){
        return selectList(new LambdaQueryWrapperX<PayrollDetailDO>()
                .eq(PayrollDetailDO::getPayrollId, payrollId));
    }

    default List<PayrollDetailDO> getDetailListByPayrollIdAndEmployeeId(Long payrollId, Long employeeId){
        return selectList(new LambdaQueryWrapperX<PayrollDetailDO>()
                .eq(PayrollDetailDO::getPayrollId, payrollId).eq(PayrollDetailDO::getEmployeeId,employeeId));
    }

    default PageResult<PayrollDetailDO> selectPage(PayrollDetailPageReqVO reqVO) {
        return selectPage(reqVO, new LambdaQueryWrapperX<PayrollDetailDO>()
                .eq(PayrollDetailDO::getPayrollId, reqVO.getPayrollId())
                .inIfPresent(PayrollDetailDO::getEmployeeId, reqVO.getEmployeeIds())
                .inIfPresent(PayrollDetailDO::getSendStatus, reqVO.getSendStatuses())
                .eqIfPresent(PayrollDetailDO::getConfirmStatus, reqVO.getConfirmStatus())
                .eqIfPresent(PayrollDetailDO::getArchived, reqVO.getArchived())
                .and(CustomFieldLabelEnum.PAYROLL_DETAIL_INFO.getValue().equals(reqVO.getWebPage()),
                        wrapper -> wrapper.isNull(PayrollDetailDO::getSendStatus).or().eq(PayrollDetailDO::getConfirmStatus, false)
                                .eq(PayrollDetailDO::getSendStatus, PayrollSendStatusEnum.WITHDRAW.getValue()))
                .and(CustomFieldLabelEnum.PAYROLL_SLIP_INFO.getValue().equals(reqVO.getWebPage()),
                        wrapper -> wrapper.isNotNull(PayrollDetailDO::getSendStatus)
                                .eq(PayrollDetailDO::getApproveResult, BpmProcessInstanceStatusEnum.APPROVE.getStatus()))
                .orderByDesc(PayrollDetailDO::getId));
    }

    default Long selectCountByPayrollIdAndEmployeeIdAndApproveResultAndConfirmStatus(Long payrollId, Collection<Long> employeeIds,
                                                                                     Integer approveResult, Boolean confirmStatus, boolean nullConfirmStatus){
        return selectCount(new LambdaQueryWrapperX<PayrollDetailDO>()
                .eq(PayrollDetailDO::getPayrollId, payrollId)
                .inIfPresent(PayrollDetailDO::getEmployeeId, employeeIds)
                .eq(PayrollDetailDO::getApproveResult, approveResult)
                .and(Objects.nonNull(confirmStatus) || nullConfirmStatus,
                        wrapper -> wrapper.eq(Objects.nonNull(confirmStatus), PayrollDetailDO::getConfirmStatus, confirmStatus)
                                .or().isNull(nullConfirmStatus, PayrollDetailDO::getConfirmStatus)));
    }

    default Long selectCountByPayrollIdAndIdAndApproveResult(Collection<Long> ids, Long payrollId, Integer approveResult, boolean nullApproveResult){
        return selectCount(new LambdaQueryWrapperX<PayrollDetailDO>()
                .eq(PayrollDetailDO::getPayrollId, payrollId)
                .inIfPresent(PayrollDetailDO::getId, ids)
                .and(wrapper -> wrapper.eq(Objects.nonNull(approveResult), PayrollDetailDO::getApproveResult, approveResult)
                        .or().isNull(nullApproveResult, PayrollDetailDO::getApproveResult)));
    }


    default Long selectCount(Collection<Long> ids){
        return selectCount(new LambdaQueryWrapperX<PayrollDetailDO>().in(PayrollDetailDO::getId, ids));
    }

    default Long selectCountByIdAndApproveResult(Collection<Long> ids, Integer approveResult){
        return selectCount(new LambdaQueryWrapperX<PayrollDetailDO>()
                .in(PayrollDetailDO::getId, ids)
                .eq(PayrollDetailDO::getApproveResult, approveResult));
    }

    default Long selectCountByIdAndSendStatus(Collection<Long> ids, Integer sendStatus){
        return selectCount(new LambdaQueryWrapperX<PayrollDetailDO>()
                .in(PayrollDetailDO::getId, ids)
                .eq(PayrollDetailDO::getSendStatus, sendStatus));
    }

    default int updateConfirmStatus(Boolean confirmStatus, Collection<Long> ids){
        return update(Wrappers.lambdaUpdate(PayrollDetailDO.class)
                .set(PayrollDetailDO::getConfirmStatus, confirmStatus)
                .in(PayrollDetailDO::getId, ids));
    }

    default Long selectCountByPayrollIdAndConfirmStatus(Long payrollId, Boolean confirmStatus){
        return selectCount(new LambdaQueryWrapperX<PayrollDetailDO>()
                .eq(PayrollDetailDO::getPayrollId, payrollId)
                .eq(PayrollDetailDO::getConfirmStatus, confirmStatus));
    }

    default Long selectCountByIdAndConfirmStatus(Collection<Long> ids, Boolean confirmStatus){
        return selectCount(new LambdaQueryWrapperX<PayrollDetailDO>()
                .in(PayrollDetailDO::getId, ids)
                .eq(PayrollDetailDO::getConfirmStatus, confirmStatus));
    }

    default Integer updateArchivedByPayrollId(Boolean archived, Long payrollId){
        return update(Wrappers.lambdaUpdate(PayrollDetailDO.class)
                .set(PayrollDetailDO::getArchived, archived)
                .eq(PayrollDetailDO::getPayrollId, payrollId));
    }

    default Long selectCountByIdAndUpdated(Collection<Long> ids, Boolean updated){
        return selectCount(new LambdaQueryWrapperX<PayrollDetailDO>()
                .in(PayrollDetailDO::getId, ids)
                .eq(PayrollDetailDO::getUpdated, updated));
    }
}